---
title: 라우팅
description: Astro를 이용한 라우팅을 소개합니다.
i18nReady: true
---

import { FileTree } from '@astrojs/starlight/components';
import RecipeLinks from "~/components/RecipeLinks.astro"
import Since from '~/components/Since.astro'
import ReadMore from '~/components/ReadMore.astro'

Astro는 **파일 기반 라우팅**을 사용하여 프로젝트 `src/pages/` 디렉터리의 파일 레이아웃을 기반으로 빌드 URL을 생성합니다.

## 페이지 간 이동

Astro는 표준 HTML [`<a>` 요소](https://developer.mozilla.org/ko/docs/Web/HTML/Element/a)를 사용하여 경로를 탐색합니다. 프레임워크별 `<Link>` 컴포넌트는 제공되지 않습니다.

```astro title="src/pages/index.astro"
<p>Read more <a href="/about/">about</a> Astro!</p>
```

## 정적 경로

`.astro` [페이지 컴포넌트](/ko/basics/astro-pages/) 및 `src/pages/` 디렉터리의 Markdown 및 MDX 파일 (`.md`, `.mdx`)은 **자동으로 웹사이트의 페이지가 됩니다**. 각 페이지의 경로는 `src/pages/` 디렉터리의 경로와 파일 이름에 해당합니다.

```diff
# Example: Static routes
src/pages/index.astro        -> mysite.com/
src/pages/about.astro        -> mysite.com/about
src/pages/about/index.astro  -> mysite.com/about
src/pages/about/me.astro     -> mysite.com/about/me
src/pages/posts/1.md         -> mysite.com/posts/1
```

:::tip
Astro 프로젝트에는 유지 관리할 별도의 "라우팅 구성"이 없습니다! `src/pages/` 디렉터리에 파일을 추가하면 새 경로가 자동으로 생성됩니다. 정적 빌드에서는 [`build.format`](/ko/reference/configuration-reference/#buildformat) 구성 옵션을 사용하여 파일 출력 형식을 맞춤설정할 수 있습니다.
:::

## 동적 경로

Astro 페이지 파일은 파일 이름에 동적 경로 매개변수를 지정하여 일치하는 여러 페이지를 생성할 수 있습니다. 예를 들어 `src/pages/authors/[author].astro` 파일은 블로그의 모든 작성자에 대한 약력 페이지를 생성합니다. `author`는 페이지 내부에서 액세스할 수 있는 _매개변수_ 가 됩니다.

Astro의 기본 정적 출력 모드에서 이러한 페이지는 빌드 시 생성되므로, 해당 파일을 가져오는 `author` 목록을 미리 결정해야 합니다. SSR 모드에서는 일치하는 경로에 대한 요청이 있을 때 페이지가 생성됩니다.

### 정적(SSG) 모드

모든 경로는 빌드 시 결정되어야 하기 때문에 동적 경로는 `params` 속성이 있는 객체 배열을 반환하는 `getStaticPaths()`를 내보내야 합니다. 이러한 각 객체는 해당 경로를 생성합니다.

`[dog].astro` 파일은 파일 이름에 동적 `dog` 매개변수를 정의하므로 `getStaticPaths()`에 의해 반환된 객체는 `params`에 `dog`을 포함해야 합니다. 그러면 페이지는 `Astro.params`를 사용하여 이 매개변수에 액세스할 수 있습니다.

```astro title="src/pages/dogs/[dog].astro"
---
export function getStaticPaths() {
  return [
    {params: {dog: 'clifford'}},
    {params: {dog: 'rover'}},
    {params: {dog: 'spot'}},
  ];
}

const { dog } = Astro.params;
---
<div>Good dog, {dog}!</div>
```

이렇게 하면 `/dogs/clifford`, `/dogs/rover`, `/dogs/spot`의 세 페이지가 생성되며 각각에 해당되는 개 이름을 표시합니다.

파일 이름에는 여러 매개변수가 포함될 수 있으며, 이 매개변수는 `getStaticPaths()`의 `params` 객체에 모두 포함되어야 합니다.

```astro title="src/pages/[lang]-[version]/info.astro"
---
export function getStaticPaths () {
 return [
    {params: {lang: 'en', version: 'v1'}},
    {params: {lang: 'fr', version: 'v2'}},
  ];
}

const { lang, version } = Astro.params;
---
...
```

그러면 `/en-v1/info` 및 `/fr-v2/info`가 생성됩니다.

매개변수는 경로의 개별 부분에 포함될 수 있습니다. 예를 들어, 위와 동일한 `getStaticPaths()`가 있는 `src/pages/[lang]/[version]/info.astro` 파일은 `/en/v1/info` 및 `/fr/v2/info` 경로를 생성합니다.

<ReadMore>[`getStaticPaths()`](/ko/reference/api-reference/#getstaticpaths)에 대해 자세히 알아보세요.</ReadMore>

<RecipeLinks slugs={["ko/recipes/i18n"]} />

#### 나머지 매개변수

URL 라우팅에 더 많은 유연성이 필요한 경우 [나머지 매개변수](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/rest_parameters) (`[...path]`)를 `.astro` 파일 이름에 추가하여 모든 깊이의 파일 경로와 일치시킵니다.

```astro title="src/pages/sequences/[...path].astro"
---
export function getStaticPaths() {
  return [
    {params: {path: 'one/two/three'}},
    {params: {path: 'four'}},
    {params: {path: undefined }}
  ]
}

const { path } = Astro.params;
---
...
```

그러면 `/sequences/one/two/three`, `/sequences/four`, `/sequences`가 생성됩니다. (나머지 매개변수를 `undefined`로 설정하면 최상위 페이지와 일치하게 됩니다.)

나머지 매개변수는 **다른 명명된 매개변수**와 함께 사용할 수 있습니다. 예를 들어 GitHub의 파일 뷰어는 다음 동적 경로로 표시될 수 있습니다.

```
/[org]/[repo]/tree/[branch]/[...file]
```
이 예시에서 `/withastro/astro/tree/main/docs/public/favicon.svg`에 대한 요청은 다음과 같은 명명된 매개변수로 분할됩니다.

```js
{
	org: 'withastro',
	repo: 'astro',
	branch: 'main',
	file: 'docs/public/favicon.svg'
}
```

#### 예: 여러 수준의 동적 페이지

다음 예시에서 나머지 매개변수 (`[...slug]`)와 `getStaticPaths()`의 [`props`](/ko/reference/api-reference/#props를-사용한-데이터-전달) 기능은 다양한 깊이의 슬러그에 대한 페이지를 생성합니다.

```astro title="src/pages/[...slug].astro"
---
export async function getStaticPaths() {
  const pages = [
    {
      slug: undefined,
      title: "Astro Store",
      text: "Welcome to the Astro store!",
    },
    {
      slug: "products",
      title: "Astro products",
      text: "We have lots of products for you",
    },
    {
      slug: "products/astro-handbook",
      title: "The ultimate Astro handbook",
      text: "If you want to learn Astro, you must read this book.",
    },
  ];
  return pages.map(({ slug, title, text }) => {
    return {
      params: { slug },
      props: { title, text },
    };
  });
}

const { title, text } = Astro.props;
---
<html>
  <head>
    <title>{title}</title>
  </head>
  <body>
    <h1>{title}</h1>
    <p>{text}</p>
  </body>
</html>
```

### 서버 (SSR) 모드

[SSR 모드](/ko/guides/server-side-rendering/)에서 동적 경로는 동일한 방식으로 정의됩니다. 임의의 문자열이나 경로와 일치하도록 파일 이름에 `[param]` 또는 `[...path]` 대괄호를 포함합니다. 그러나 경로가 더 이상 미리 빌드되지 않기 때문에 페이지는 일치하는 모든 경로에 제공됩니다. 이는 "정적" 경로가 아니므로 `getStaticPaths`를 사용하면 안 됩니다.

```astro title="src/pages/resources/[resource]/[id].astro"
---
const { resource, id } = Astro.params;
---
<h1>{resource}: {id}</h1>
```

이 페이지는 `resource` 및 `id` 값 (`resources/users/1`, `resources/colors/blue` 등)에 대해 제공됩니다.

#### SSR에 대한 `[...slug]` 예시 수정

SSR 페이지는 `getStaticPaths()`를 사용할 수 없기 때문에 props를 받을 수 없습니다. [이전 예시](#예-여러-수준의-동적-페이지)는 객체에서 `slug` 매개변수 값을 조회하여 SSR 모드에 맞게 조정할 수 있습니다. 경로가 루트 ("/")에 있으면 슬러그 매개변수는 `undefined`가 됩니다. 객체에 값이 없으면 404 페이지로 리디렉션됩니다.

```astro title="src/pages/[...slug].astro"
---
const pages = [
	{
		slug: undefined,
		title: 'Astro Store',
		text: 'Welcome to the Astro store!',
	},
	{
		slug: 'products',
		title: 'Astro products',
		text: 'We have lots of products for you',
	},
	{
		slug: 'products/astro-handbook',
		title: 'The ultimate Astro handbook',
		text: 'If you want to learn Astro, you must read this book.',
	}
];

const { slug } = Astro.params;
const page = pages.find((page) => page.slug === slug);
if (!page) return Astro.redirect("/404");
const { title, text } = page;
---
<html>
<head>
  <title>{title}</title>
</head>
<body>
  <h1>{title}</h1>
  <p>{text}</p>
</body>
</html>
```

## 리디렉션

사이트 구조가 영구적으로 변경되었거나 인증된 경로에 로그인하는 등의 작업에 대한 응답으로 사용자를 새 페이지로 리디렉션해야 하는 경우가 있습니다.

Astro 구성에서 [영구적으로 이동된 페이지로 사용자를 리디렉션](#구성된-리디렉션)하는 규칙을 정의할 수 있습니다. 또는 사용자가 여러분의 사이트를 사용할 때 [사용자를 동적으로 리디렉션](#동적-리디렉션)할 수도 있습니다.

### 구성된 리디렉션

<p><Since v="2.9.0" /></p>

`redirects` 값을 사용하여 Astro 구성에서 영구 리디렉션 매핑을 지정할 수 있습니다. 대부분의 리디렉션에서 이는 이전 경로를 새 경로로 매핑합니다.

```js title="astro.config.mjs" {4-6}
import { defineConfig } from 'astro/config';

export default defineConfig({
  redirects: {
    '/old-page': '/new-page'
  }
});
```

이러한 리디렉션은 파일 기반 경로와 동일한 규칙을 따릅니다. 새 경로와 이전 경로 모두에 동일한 매개변수가 포함되어 있는 한 동적 경로가 허용됩니다. 예를 들면 다음과 같습니다.

```js
{
  "/blog/[...slug]": "/articles/[...slug]"
}
```

SSR 또는 정적 어댑터를 사용하면 객체를 값으로 제공하여 새로운 `destination` 외에 `status` 코드를 지정할 수도 있습니다.

```js title="astro.config.mjs" {5-8}
import { defineConfig } from 'astro/config';

export default defineConfig({
  redirects: {
    '/old-page': {
      status: 302,
      destination: '/new-page'
    }
  }
});
```

`astro build`를 실행하면 Astro는 기본적으로 [meta refresh](https://developer.mozilla.org/ko/docs/Web/HTML/Element/meta) 태그가 포함된 HTML 파일을 출력합니다. 지원되는 어댑터는 대신 리디렉션을 사용하여 호스트의 구성 파일을 작성합니다.

상태 코드는 기본적으로 `301`입니다. HTML 파일로 빌드하는 경우 서버에서는 상태 코드를 사용하지 않습니다.

### 동적 리디렉션

`Astro` 전역에서 `Astro.redirect` 메소드를 사용하면 다른 페이지로 동적으로 리디렉션할 수 있습니다. 쿠키에서 세션을 가져와 사용자가 로그인했는지 확인한 후 이 작업을 수행할 수 있습니다.

```astro title="src/pages/account.astro" {8}
---
import { isLoggedIn } from '../utils';

const cookie = Astro.request.headers.get('cookie');

// 사용자가 로그인되어 있지 않은 경우 로그인 페이지로 리디렉션
if (!isLoggedIn(cookie)) {
  return Astro.redirect('/login');
}
---
<html>
  <!-- 페이지... -->
</html>
```

## 경로 우선순위

정의된 여러 경로가 동일한 URL 경로를 빌드하려고 시도할 수 있습니다. 예를 들어, 다음 경로는 모두 `/posts/create`를 빌드할 수 있습니다.

<FileTree>
- src/pages/
  - [...slug].astro
  - posts/
    - create.astro
    - [page].astro
    - [pid].ts
    - [...slug].astro
</FileTree>

Astro는 페이지를 빌드하는 데 어떤 경로를 사용해야 하는지 알아야 합니다. 이를 위해 다음 규칙에 따라 순서대로 정렬합니다.

- 더 많은 경로 세그먼트를 가진 경로가 덜 구체적인 경로보다 우선합니다. 위 예시에서 `/posts/` 아래의 모든 경로는 루트의 `/[...slug].astro`보다 우선합니다.
- 경로 매개변수가 없는 정적 경로는 동적 경로보다 우선합니다. 예: `/posts/create.astro`는 예시의 다른 모든 경로보다 우선합니다.
- 명명된 매개변수를 사용하는 동적 경로는 나머지 매개변수보다 우선합니다. 예: `/posts/[page].astro`는 `/posts/[...slug].astro`보다 우선합니다.
- 사전 렌더링된 동적 경로는 서버 동적 경로보다 우선합니다.
- 엔드포인트가 페이지보다 우선합니다.
- 위 규칙 중 어느 것도 순서를 결정하지 않으면 노드 설치의 기본 로케일을 기준으로 경로가 알파벳순으로 정렬됩니다.

위 예시에서 규칙이 요청된 URL을 HTML 작성에 사용된 경로와 일치시키는 방법에 대한 몇 가지 예시는 다음과 같습니다.

- `pages/posts/create.astro` - `/posts/create`만 빌드합니다.
- `pages/posts/[pid].ts` - `/posts/abc`, `/posts/xyz` 등을 빌드하지만 `/posts/create`는 빌드하지 않습니다.
- `pages/posts/[page].astro` - `/posts/1`, `/posts/2` 등을 빌드하지만 `/posts/create`, `/posts/abc`, `/posts/xyz`는 빌드하지 않습니다.
- `pages/posts/[...slug].astro` - `/posts/1/2`, `/posts/a/b/c` 등을 빌드하지만 `/posts/create`, `/posts/1`, `/posts/abc` 등은 빌드하지 않습니다.
- `pages/[...slug].astro` - `/abc`, `/xyz`, `/abc/xyz` 등을 빌드하지만 `/posts/create`, `/posts/1`, `/posts/abc` 등은 빌드하지 않습니다.

## 페이지네이션

Astro는 여러 페이지로 분할해야 하는 대규모 데이터 컬렉션에 대해 내장된 페이지네이션을 지원합니다. Astro는 이전/다음 페이지 URL, 총 페이지 수 등을 포함한 일반적인 페이지네이션 속성을 생성합니다.

페이지가 매겨진 경로 이름은 표준 동적 경로와 동일한 `[대괄호]` 구문을 사용해야 합니다. 예를 들어 파일 이름 `/astronauts/[page].astro`는 `/astronauts/1`, `/astronauts/2` 등에 대한 경로를 생성합니다. 여기서 `[page]`는 생성된 페이지 번호입니다.

`paginate()` 함수를 사용하여 다음과 같은 값 배열에 대한 이러한 페이지를 생성할 수 있습니다.

```astro /{ (paginate) }/ /paginate\\(.*\\)/ /(?<=const.*)(page)/ /page\\.[a-zA-Z]+/
---
// src/pages/astronauts/[page].astro
export async function getStaticPaths({ paginate }) {
  const astronautPages = [{
    astronaut: 'Neil Armstrong',
  }, {
    astronaut: 'Buzz Aldrin',
  }, {
    astronaut: 'Sally Ride',
  }, {
    astronaut: 'John Glenn',
  }];
  // astronauts 배열에서 한 페이지에 2개의 페이지를 생성합니다.
  return paginate(astronautPages, { pageSize: 2 });
}
// 페이지가 매겨진 모든 데이터는 "page" prop으로 전달됩니다.
const { page } = Astro.props;
---

<!--현재 페이지 번호를 표시합니다. Astro.params.page도 사용할 수 있습니다!-->
<h1>Page {page.currentPage}</h1>
<ul>
  <!--astronauts 정보 배열 나열-->
  {page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
```

그러면 한 페이지에 2개의 항목이 포함된 다음 페이지가 생성됩니다.
- `/astronauts/1` - 페이지 1: "Neil Armstrong" 및 "Buzz Aldrin" 표시
- `/astronauts/2` - 페이지 2: "Sally Ride" 및 "John Glenn" 표시

### `page` prop

`paginate()` 함수를 사용하면 각 페이지는 `page` prop을 통해 데이터가 전달됩니다. `page` prop에는 유용한 속성이 많이 있지만 주요 내용은 다음과 같습니다.

- **page.data** - `paginate()` 함수에 전달한 페이지의 데이터 조각을 포함하는 배열
- **page.url.next** - 세트의 다음 페이지에 대한 링크
- **page.url.prev** - 세트의 이전 페이지에 대한 링크

```astro /(?<=const.*)(page)/ /page\\.[a-zA-Z]+(?:\\.(?:prev|next))?/
---
// src/pages/astronauts/[page].astro
// 이전 예시와 동일한 { astronaut } 객체 목록에 페이지를 매깁니다.
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
<h1>Page {page.currentPage}</h1>
<ul>
  {page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
{page.url.prev ? <a href={page.url.prev}>Previous</a> : null}
{page.url.next ? <a href={page.url.next}>Next</a> : null}
```

#### 완전한 API 참조

```ts
interface Page<T = any> {
	/** result */
	data: T[];
	/** 메타데이터 */
	/** 0부터 시작하는 페이지의 첫 번째 항목 수 */
	start: number;
	/** 0부터 시작하는 페이지의 마지막 항목 수 */
	end: number;
	/** 총 결과 수 */
	total: number;
	/** 1부터 시작하는 현재 페이지 번호 */
	currentPage: number;
	/** 페이지당 항목 수(기본값: 25) */
	size: number;
	/** 마지막 페이지 수 */
	lastPage: number;
	url: {
		/** 현재 페이지의 URL */
		current: string;
		/** 이전 페이지의 URL (존재하는 경우) */
		prev: string | undefined;
		/** 다음 페이지의 URL (존재하는 경우) */
		next: string | undefined;
	};
}
```

### 중첩된 페이지네이션

페이지네이션의 고급 사용 사례는 **중첩 페이지네이션**입니다. 이는 페이지네이션이 다른 동적 경로 매개변수와 결합되는 경우입니다. 중첩된 페이지네이션을 사용하여 페이지가 매겨진 컬렉션을 일부 속성이나 태그별로 그룹화할 수 있습니다.

예를 들어, 페이지가 매겨진 Markdown 게시물을 일부 태그로 그룹화하려면 다음 URL과 일치하는 `/src/pages/[tag]/[page].astro` 페이지를 생성하여 중첩된 페이지네이션을 사용합니다.

- `/red/1` (태그=red)
- `/red/2` (태그=red)
- `/blue/1` (태그=blue)
- `/green/1` (태그=green)

중첩된 페이지네이션은 `getStaticPaths()`에서 `paginate()` 결과 배열을 각 그룹마다 하나씩 반환하여 작동합니다.

다음 예시에서는 위에 나열된 URL을 작성하기 위해 중첩된 페이지네이션을 구현합니다.

```astro /(?:[(]|=== )(tag)/ "params: { tag }" /const [{ ]*(page|params)/
---
// src/pages/[tag]/[page].astro
export async function getStaticPaths({ paginate }) {
  const allTags = ['red', 'blue', 'green'];
  const allPosts = await Astro.glob('../../posts/*.md');
  // 모든 태그에 대해 paginate() 결과를 반환합니다.
  // `{params: {tag}}`를 `paginate()`에 전달했는지 확인합니다.
  // Astro가 결과가 어떤 태그 그룹에 대한 것인지 알 수 있도록 합니다.
  return allTags.flatMap((tag) => {
    const filteredPosts = allPosts.filter((post) => post.frontmatter.tag === tag);
    return paginate(filteredPosts, {
      params: { tag },
      pageSize: 10
    });
  });
}
const { page } = Astro.props;
const params = Astro.params;
```

## 페이지 제외

페이지나 디렉터리 이름 앞에 밑줄 (`_`)을 붙여서 빌드되지 않도록 제외할 수 있습니다. `_` 접두사가 붙은 파일은 라우터에서 인식되지 않으며 `dist/` 디렉터리에 배치되지 않습니다.

이를 사용하여 페이지를 일시적으로 비활성화하고 테스트, 유틸리티 및 컴포넌트를 관련 페이지와 동일한 폴더에 넣을 수도 있습니다.

이 예시에서는 `src/pages/index.astro` 및 `src/pages/posts/post1.md` 파일만 페이지 경로 및 HTML 파일로 빌드됩니다.

<FileTree>
- src/pages/
  - _hidden-directory/
    - page1.md
    - page2.md
  - _hidden-page.astro
  - **index.astro**
  - posts/
    - _SomeComponent.astro
    - _utils.js
    - **post1.md**
</FileTree>
